home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC]
/
NeXTSTEP 3.3 Dev Intel.iso
/
NextDeveloper
/
Source
/
GNU
/
debug
/
Common
/
RelocManager.m
< prev
next >
Wrap
Text File
|
1994-11-29
|
9KB
|
378 lines
#import "RelocManager.h"
#import <stdlib.h>
#import <string.h>
#import <mach-o/loader.h>
#import <libc.h>
@implementation RelocManager
-init
{
rmFlags.invalid = YES;
rmFlags.shouldSortRelocs = YES;
return self;
}
-free
{
[self invalidate];
return [super free];
}
int compareRelocsSort(const void *v1, const void *v2)
{
const Reloc *r1 = v1, *r2 = v2;
pointer_t a1 = r1->address, a2 = r2->address;
return a1 < a2 ? -1 : (a1 == a2 ? 0 : 1);
}
int compareRelocsSearch(const void *v1, const void *v2)
{
const Reloc *r1 = v1, *r2 = v2;
pointer_t address = r1->address;
return address < r2->address ? -1 : (address >= r2->maxAddress ? 1 : 0);
}
-(Reloc *)relocFor: (const void *)pointer
{
Reloc *reloc;
int count;
BOOL found, tooFar;
if (rmFlags.invalid)
[self readInAllRelocs];
if (lastReloc
&& (lastReloc->address <= (pointer_t)pointer)
&& ((pointer_t)pointer < (lastReloc->maxAddress)))
return lastReloc;
else {
#if 1
Reloc keyReloc;
keyReloc.address = (pointer_t)pointer;
if (reloc = bsearch(&keyReloc, relocs, numRelocs, relocSize, compareRelocsSearch))
found = YES;
else
found = NO;
#else
reloc = relocs;
for (count = numRelocs, found = NO, tooFar = NO;
count && !found && !tooFar; count--) {
if ((pointer_t)pointer < (reloc->maxAddress)) {
if (reloc->address <= (pointer_t)pointer)
found = YES;
else
tooFar = YES;
} else
((void *)reloc) += relocSize;
}
#endif
if (found && (reloc->rFlags.readIn || [self readInReloc: reloc])) {
lastReloc = reloc;
return reloc;
} else
return NULL;
}
}
-(BOOL)readInReloc: (Reloc *)reloc
{
[self subclassResponsibility: _cmd];
return NO;
}
-(void)_readInAllRelocs
{
[self subclassResponsibility: _cmd];
}
-(void)readInAllRelocs
{
[self _readInAllRelocs];
if (rmFlags.shouldSortRelocs)
qsort(relocs, numRelocs, relocSize, compareRelocsSort);
}
-invalidate
{
if (rmFlags.invalid)
return self;
else {
if (relocs) {
free(relocs); relocs = NULL;
}
numRelocs = 0;
lastReloc = NULL;
rmFlags.invalid = YES;
return self;
}
}
-(Reloc *)oldRelocFor: (const void *)pointer
{
int count;
BOOL found;
Reloc *reloc;
if (lastReloc
&& (lastReloc->data <= (pointer_t)pointer)
&& ((pointer_t)pointer < lastReloc->maxData))
return lastReloc;
else {
reloc = relocs;
for (count = numRelocs, found = NO; count && !found; count--) {
if (reloc->rFlags.readIn && (reloc->data <= (pointer_t)pointer)
&& ((pointer_t)pointer < reloc->maxData))
found = YES;
else
((void *)reloc) += relocSize;
}
if (found) {
lastReloc = reloc;
return reloc;
} else
return NULL;
}
}
-(void *)originalPointerFor: (const void *)pointer
{
Reloc *reloc = [self oldRelocFor: pointer];
if (reloc)
return (void *)(reloc->address + (pointer - reloc->data));
else
return NULL;
}
-(void *)pointerFor: (const void *)pointer
{
Reloc *reloc;
if (pointer && (reloc = [self relocFor: pointer]))
return (void *)((pointer_t)pointer + reloc->displacement);
else
return NULL;
}
-(char *)pointerForString: (const char *)pointer isNullTerminated: (BOOL *)isNT
{
char *retPointer;
Reloc *reloc;
char *string;
if (pointer && (reloc = [self relocFor: pointer])) {
retPointer = (char *)((pointer_t)pointer + reloc->displacement);
for (string = retPointer;
*string && ((pointer_t)string < reloc->maxData);
string++);
*isNT = *string ? NO : YES;
return retPointer;
} else{
*isNT = NO;
return NULL;
}
}
-(char *)pointerForString: (const char *)string
{
BOOL isNT;
char *retPointer;
if ((retPointer = [self pointerForString: string isNullTerminated: &isNT])
&& isNT)
return retPointer;
else
return NULL;
}
-(void *)pointerFor: (const void *)pointer withSize: (int)size
{
Reloc *reloc;
pointer_t newPointer;
if (pointer && (reloc = [self relocFor: pointer])) {
newPointer = (pointer_t)pointer + reloc->displacement;
if ((newPointer + size) <= reloc->maxData)
return (void *)newPointer;
else
return NULL;
} else
return NULL;
}
-(id)pointerForID: (const id)pointer
{
Class theClass;
struct _ObjectID {
@defs(Object)
} *newID;
if (pointer
&& (newID = [self pointerFor: pointer withSize: sizeof(id)])
&& (theClass = [self pointerFor: newID->isa
withSize: sizeof(Class)])
&& (newID
= [self pointerFor: pointer withSize: theClass->instance_size]))
return (id)newID;
else
return nil;
}
-(int)getDataAt: (const void *)start for: (int)numBytes into: (void *)data
{
Reloc *reloc = [self relocFor: start];
int numBytesInReloc;
if (reloc) {
numBytesInReloc = reloc->maxAddress - (int)start;
if (numBytes > numBytesInReloc)
numBytes = numBytesInReloc;
memcpy(data,
(void *)(reloc->data + ((pointer_t)start - reloc->address)),
numBytes);
return numBytes;
} else
return 0;
}
-(struct mach_header *)getMachHeader
{
[self subclassResponsibility: _cmd];
return NULL;
}
-(int)getNumMachHeaders
{
[self subclassResponsibility: _cmd];
return 0;
}
-(struct mach_header **)getMachHeaders
{
[self subclassResponsibility: _cmd];
return NULL;
}
-(struct mach_header **)getMachHeadersWithNames: (char ***)names
{
[self subclassResponsibility: _cmd];
return NULL;
}
-(void *)getSectData: (STR)segName
section: (STR)sectName
size: (int *)pSize
forHeader: (struct mach_header *)header
{
void *data = getsectdatafromheader(header, segName, sectName, pSize);
return [self pointerFor: data withSize: *pSize];
}
-(void *)getSectData: (STR)segName
section: (STR)sectName
size: (int *)pSize
{
return [self getSectData: segName
section: sectName
size: pSize
forHeader: [self getMachHeader]];
}
-(const struct section *)getSeg: (STR)segName sect: (STR)sectName
{
return getsectbynamefromheader([self getMachHeader], segName, sectName);
}
-(const struct section *)firstSection
{
struct mach_header *header = [self getMachHeader];
int i;
struct load_command *loadCmd;
for (i = 0, loadCmd = (struct load_command *)(header + 1);
i < header->ncmds;
i++, ((void *)loadCmd) += loadCmd->cmdsize) {
if (loadCmd->cmd == LC_SEGMENT) {
struct segment_command *segCmd = (struct segment_command *)loadCmd;
if (segCmd->nsects)
return (struct section *)(segCmd + 1);
}
}
return NULL;
}
-(unsigned)getMaximumAddressForHeader: (struct mach_header *)header
{
int i;
struct load_command *loadCmd;
unsigned maxAddr = 0;
for (i = 0, loadCmd = (struct load_command *)(header + 1);
i < header->ncmds;
i++, ((void *)loadCmd) += loadCmd->cmdsize) {
if (loadCmd->cmd == LC_SEGMENT) {
struct segment_command *segCmd = (struct segment_command *)loadCmd;
if ((segCmd->vmaddr + segCmd->vmsize) > maxAddr)
maxAddr = segCmd->vmaddr + segCmd->vmsize;
}
}
return maxAddr;
}
-(struct segment_command *)getSegment: (const char *)segName
{
int i;
struct load_command *loadCmd;
struct segment_command *foundSeg = NULL;
struct mach_header *header = [self getMachHeader];
for (i = 0, loadCmd = (struct load_command *)(header + 1);
i < header->ncmds && !foundSeg;
i++, ((void *)loadCmd) += loadCmd->cmdsize) {
if (loadCmd->cmd == LC_SEGMENT) {
struct segment_command *segCmd = (struct segment_command *)loadCmd;
if (strcmp(segName, segCmd->segname) == 0)
foundSeg = segCmd;
}
}
return foundSeg;
}
-(unsigned)getMaximumAddressForSegment: (const char *)segName
{
int i;
struct load_command *loadCmd;
unsigned maxAddr = 0;
struct mach_header *header = [self getMachHeader];
for (i = 0, loadCmd = (struct load_command *)(header + 1);
i < header->ncmds;
i++, ((void *)loadCmd) += loadCmd->cmdsize) {
if (loadCmd->cmd == LC_SEGMENT) {
struct segment_command *segCmd = (struct segment_command *)loadCmd;
struct section *section;
int nSects;
for (nSects = segCmd->nsects,
section = (struct section *)(segCmd + 1);
nSects;
nSects--, section++) {
if (strcmp(section->segname, segName) == 0) {
if ((section->addr + section->size) > maxAddr)
maxAddr = (section->addr + section->size);
}
}
}
}
return maxAddr;
}
-(unsigned)getMaximumAddress
{
return [self getMaximumAddressForHeader: [self getMachHeader]];
}
-(unsigned)getMaximumTextAddress
{
return [self getMaximumAddressForSegment: "__TEXT"];
}
-(unsigned)getMaximumDataAddress
{
return [self getMaximumAddressForSegment: "__DATA"];
}
@end